/*
* Copyright (c) 2007, Nubo Technologies
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
*    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*    * Neither the name of the Nubo Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.nubotech.gwt.oss.browser.client.ui;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.nubotech.gwt.oss.browser.client.State;
import com.nubotech.gwt.oss.client.AccessControlPolicy;
import com.nubotech.gwt.oss.client.AccessControlPolicyCallback;
import com.nubotech.gwt.oss.client.Grant;
import com.nubotech.gwt.oss.client.Grantee;
import com.nubotech.gwt.oss.client.Group;
import com.nubotech.gwt.oss.client.EmailUser;
import com.nubotech.gwt.oss.client.ObjectHolder;
import com.nubotech.gwt.oss.client.OnlineStorageService;
import com.nubotech.gwt.oss.client.OnlineStorageServiceFactory;
import com.nubotech.gwt.oss.client.auth.AuthenticationManager;
import com.nubotech.gwt.oss.client.auth.Credential;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 * @author jonnakkerud
 */
public class EditAccessControlPolicyView extends Composite implements AccessControlPolicyCallback {
    private State state;
    private AccessControlPolicy acp;
    private DockPanel main;
    private VerticalPanel grantList;
    
    /** Creates a new instance of EditAccessControlPolicyView */
    public EditAccessControlPolicyView(State state) {
        this.state = state;
        initWidget(main = new DockPanel());      
    }
    
    public void onLoad() {
        DeferredCommand.addCommand(new Command() {
            public void execute() {
                initGui();
            }
        });
    }
    
    private void initGui() {
        
        // get the policy from the selection
        Iterator itr = state.getObjectHolderListModel().getSelectedContent().iterator();
        // TODO allow multiselect
        if (itr.hasNext()) {
            ObjectHolder holder = (ObjectHolder)itr.next();
            AuthenticationManager mgr = AuthenticationManager.instance();
            Credential c = mgr.getLogin();
            OnlineStorageService fs = OnlineStorageServiceFactory.getService(c);
            fs.getAccessControlPolicy(state.getCurrentBucket().getName(), holder.getKey(), this);  
        }
        
        HorizontalPanel buttonsP = new HorizontalPanel();
        main.add(buttonsP, DockPanel.SOUTH);
        
        Button updateB = new Button("Update");
        updateB.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                update();
            }
        });
        buttonsP.add(updateB);       
    }
    
    private void update() {
        Iterator itr = grantList.iterator();
        while(itr.hasNext()) {
            Widget w = (Widget)itr.next();
            if (w instanceof GrantPanel) {
                GrantPanel gp = (GrantPanel)w;
                acp.getAccessControlList().addAll(gp.getGrantList());
            }
        }
        
        // update
        itr = state.getObjectHolderListModel().getSelectedContent().iterator();
        // TODO allow multiselect
        if (itr.hasNext()) {
            ObjectHolder holder = (ObjectHolder)itr.next();
            AuthenticationManager mgr = AuthenticationManager.instance();
            Credential c = mgr.getLogin();
            OnlineStorageService fs = OnlineStorageServiceFactory.getService(c);
            fs.updateAccessControlPolicy(state.getCurrentBucket().getName(), holder.getKey(), acp);  
        }
        
    }

    public void onAccessControlPolicy(AccessControlPolicy accessControlPolicy) {
        grantList = new VerticalPanel();
        grantList.setSpacing(5);
        main.add(grantList, DockPanel.CENTER);

        acp = new AccessControlPolicy();
        acp.setOwnerDisplayName(accessControlPolicy.getOwnerDisplayName());
        acp.setOwnerId(accessControlPolicy.getOwnerId());
        
        // CanonicalUser
        //Widget w = createGrantTypeWidget(accessControlPolicy, Grantee.CANONICAL_USER);
        //vpanel.add(w);
        
        // EmailUser
        GrantPanel w = createGrantPanel(accessControlPolicy, Grantee.EMAIL_USER);
        grantList.add(w);

        // Group
        w = createGrantPanel(accessControlPolicy, Grantee.GROUP);
        grantList.add(w);        
    }

    private GrantPanel createGrantPanel(AccessControlPolicy accessControlPolicy, String type) {
        return new GrantPanel(accessControlPolicy, type);
    }
    
    class GrantPanel extends VerticalPanel {
        private AccessControlPolicy accessControlPolicy;
        private String type;
        private FlexTable table;
        
        public GrantPanel(AccessControlPolicy accessControlPolicy, String type) {
            this.accessControlPolicy = accessControlPolicy;
            this.type = type;
            initGui();
        }
        
        private void initGui() {
            setSpacing(3);
            
            Label heading = new Label(type);
            heading.setStyleName("caption");
            add(heading);
            
            table = new FlexTable();
            add(table);
            
            int row = 0;
            Iterator itr = accessControlPolicy.getGrantsByType(type).iterator();
            while(itr.hasNext()) {
                addRow(row, (Grant)itr.next());
            }
            
            HorizontalPanel actionsPanel = new HorizontalPanel();
            actionsPanel.setWidth("100%");
            add(actionsPanel);
            Button addB = new Button("Add");
            addB.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    Grant g = new Grant();
                    Grantee gt = Grantee.createGrantee(type);                    
                    g.setGrantee(gt);
                    addRow(table.getRowCount(), g);
                }
            });
            actionsPanel.add(addB);
            actionsPanel.setCellHorizontalAlignment(addB, DockPanel.ALIGN_RIGHT);
        }
        
        private void addRow(final int row, Grant g) {
            Button removeB = new Button("X");
            removeB.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    table.removeRow(row);
                }
            });
            
            table.setWidget(row, 0, removeB);
            table.setWidget(row, 1, createGranteeWidget(g.getGrantee()));
            table.setWidget(row, 2, createPermissionWidget(g));
        }
        
        public List getGrantList() {
            List result = new ArrayList();
            
            for (int i = 0; i < table.getRowCount(); i++) {
                Grant grant = new Grant();
                GranteeWidget gw = (GranteeWidget) table.getWidget(i, 1);
                grant.setGrantee(gw.getGrantee());
                
                Widget p = table.getWidget(i, 2);
                grant.setPermission(getWidgetValue(p));
                result.add(grant);
            }
            
            return result;
        }
        
        private String getWidgetValue(Widget w) {
            String result = null;
            
            if (w instanceof TextBox) {
                result = ((TextBox)w).getText();
            } else if (w instanceof ListBox) {
                ListBox lb = (ListBox)w;
                result = lb.getItemText(lb.getSelectedIndex());
            }
            
            return result;
        }
        
        private ListBox createPermissionWidget(Grant g) {
            ListBox list = new ListBox();
            list.addItem("READ");
            list.addItem("WRITE");
            list.addItem("READ_ACP");
            list.addItem("WRITE_ACP");
            list.addItem("FULL_CONTROL");
            
            for (int i = 0; i < list.getItemCount(); i++) {
                if (list.getItemText(i).equals(g.getPermission())) {
                    list.setSelectedIndex(i);
                    break;
                }
            }
            
            return list;
        }
        
        private GranteeWidget createGranteeWidget(Grantee grantee) {
            return new GranteeWidget(grantee);
        }
        
    }
    
    class GranteeWidget extends Composite {
        private Grantee grantee;
        
        public GranteeWidget(Grantee grantee) {
            this.grantee = grantee;
            initGui();           
        }
        
        private void initGui() {
            Widget w = null;
            if (Grantee.CANONICAL_USER.equals(grantee.getType())) {
                //  nothing ...
            } else if (Grantee.EMAIL_USER.equals(grantee.getType())) {
                TextBox tb = new TextBox();
                String v = (String) grantee.getProperties().get("EmailAddress");
                tb.setText(v != null ? v : "");
                w = tb;
            }
            else if (Grantee.GROUP.equals(grantee.getType())) {
                ListBox lb = new ListBox();
                lb.addItem(Group.ALL_USERS_GROUP);
                lb.addItem(Group.AUTHENTICATED_USERS_GROUP);
                String v = (String) grantee.getProperties().get("URI");
                if (v != null) {
                    if (Group.ALL_USERS_GROUP.equals(v)) {
                        lb.setSelectedIndex(0);
                    }
                    else {
                        lb.setSelectedIndex(1);
                    }
                }
                w = lb;
            }
            initWidget(w);
        }
        
        public Grantee getGrantee() {
            Map props = new HashMap();
            // set the value
            if (Grantee.CANONICAL_USER.equals(grantee.getType())) {
                //  nothing ...
            } else if (Grantee.EMAIL_USER.equals(grantee.getType())) {
                TextBox tb = (TextBox)getWidget();
                ((EmailUser)grantee).setEmailAddress(tb.getText());
            }
            else if (Grantee.GROUP.equals(grantee.getType())) {
                ListBox lb = (ListBox)getWidget();
                ((Group)grantee).setGroupType(lb.getValue(lb.getSelectedIndex()));
            }   
            return grantee;
        }
    }
    
}
